package com.travel.util;

import org.bytedeco.opencv.presets.opencv_core;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;


/**
 * @ClassName RedisUtil
 * @Author Lizhou
 * @Date 2019-08-03 17:29:29
 * @Version 1.0
 **/
@Component
public class RedisUtil {

    @Autowired
    private RedisTemplate<String, String> template;

    /**
     * 读取数据
     *
     * @param key
     * @return
     */
    public String get(final String key) {
        return template.opsForValue().get(key);
    }

    /**
     * 写入数据
     */
    public boolean set(final String key, String value) {
        boolean res = false;
        try {
            template.opsForValue().set(key, value);
            res = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return res;
    }

    /**
     * 根据key更新数据
     */
    public boolean update(final String key, String value) {
        boolean res = false;
        try {
            template.opsForValue().getAndSet(key, value);
            res = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return res;
    }

    /**
     * 根据key删除数据
     */
    public boolean del(final String key) {
        boolean res = false;
        try {
            template.delete(key);
            res = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return res;
    }

    /**
     * 是否存在key
     */
    public boolean hasKey(final String key) {
        boolean res = false;
        try {
            res = Boolean.TRUE.equals(template.hasKey(key));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return res;
    }

    /**
     * 写入缓存,并设置过期时间
     *
     * @param key
     * @param value
     * @param timeout
     * @param unit 时间单位枚举的类型
     * 1、ANOSECONDS：纳秒（=千分之一微妙）
     * 2、MICROSECONDS：微妙（=千分之一毫秒）
     * 3、MILLISECONDS：毫秒（=千分之一秒）
     * 4、SECONDS：秒
     * 5、MINUTES：分钟
     * 6、HOURS：小时
     * 7、DAYS：天
     * @return
     */
    public boolean set(final String key, String value, long timeout, TimeUnit unit) {
        boolean result = false;
        try {
            template.opsForValue().set(key, value, timeout, unit);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }


    /**
     * 给指定的key设置存活时间
     * 默认为-1，表示永久不失效
     */
    public boolean setExpire(final String key, long seconds) {
        boolean res = false;
        try {
            if (0 < seconds) {
                res = Boolean.TRUE.equals(template.expire(key, seconds, TimeUnit.SECONDS));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return res;
    }

    /**
     * 获取指定key的剩余存活时间
     * 默认为-1，表示永久不失效，-2表示该key不存在
     */
    public long getExpire(final String key) {
        long res = 0;
        try {
            res = template.getExpire(key, TimeUnit.MINUTES);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return res;
    }

    /**
     * 移除指定key的有效时间
     * 当key的有效时间为-1即永久不失效和当key不存在时返回false，否则返回true
     */
    public boolean persist(final String key) {
        boolean res = false;
        try {
            res = Boolean.TRUE.equals(template.persist(key));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return res;
    }


    /**
     * 无序不重复集合
     *
     * @param setName 集名称
     * @param value   内容
     * @return boolean
     */
    public boolean setAdd(String setName, String value){
        Long size = 0L;
        if(this.hasKey(setName))
            size = template.opsForSet().size(setName);
        boolean res = false;
        try{
            res = size < template.opsForSet().add(setName,value);
        }catch (Exception e){
            e.printStackTrace();
        }
        return res;
    }

    /**
     * 检测set内容是否存在
     *
     * @param setName set名称
     * @param value   内容
     * @return boolean
     */
    public boolean setMember(String setName,String value){
        boolean res = false;

        try{
            res = Boolean.TRUE.equals(template.opsForSet().isMember(setName, value));
        }catch (Exception e){
            e.printStackTrace();
        }
        return res;
    }


    /**
     * 设置添加(List(String))
     *
     * @param setName 集名称
     * @param values  值(List(String))
     * @return boolean(只要有一个添加失败那么就返回false)
     */
    public boolean setAdds(String setName, List<String> values){
        boolean res = true;
        for (String v:values){
            res &= this.setAdd(setName,v);
        }
        return res;
    }


    /**
     * Key是否存在
     *
     * @param setName 集名称
     * @return boolean
     */
    public boolean SetExists(String setName){
        boolean res = false;
        try{
            res = Boolean.TRUE.equals(template.persist(setName));
        }catch (Exception e){
            e.printStackTrace();
        }
        return res;
    }

    /**
     * 删除键
     * 除非执行出错就一定会返回true
     *
     * @param key 关键
     * @return boolean
     */
    public boolean deleteKey(String key){
        //除非执行出错就一定会返回true
        boolean res = true;
        try{
            //如果该key存在则删除掉
            if(hasKey(key))
                res = del(key);
        }catch (Exception e){
            e.printStackTrace();
            ConsoleOutputControl.getOutputString_33("Error deleteKey"+key);
            return false;
        }
        return res;
    }


    /**
     * 列表-追加值
     *
     * @param key   Redis键名
     * @param value 列表值
     */
    public void lPush(String key, String value) {
        ListOperations<String, String> list = template.opsForList();
        list.leftPush(key, value);
    }

    /**
     * 列表-删除值
     *
     * @param key   Redis键名
     * @param value 列表值
     */
    public void lRemove(String key, String value) {
        ListOperations<String, String> list = template.opsForList();
        list.remove(key, 0, value);
    }




    /**
     * 列表-获取指定范围数据
     *
     * @param key   Redis键名
     * @param start 开始行号（start:0，end:-1查询所有值）
     * @param end   结束行号
     * @return 列表
     */
    public List<String> lRange(String key, long start, long end) {
        ListOperations<String, String> list = template.opsForList();
        return list.range(key, start, end);
    }

    public List<String> getLRange(String key, long start, long end){
        return template.opsForList().range(key, start, end);
    }


    /**
     * 删除键--根据键的前缀
     *
     * @param keyPre 键前缀
     * @return {@link List}<{@link String}>
     */
    public boolean delKeys(String keyPre){
        try{
            Set<String> keys = template.keys(keyPre+"*");
            if(null != keys){
                for (String s:keys){
                    deleteKey(s);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
       return true;

    }

}